package com.apobates.forum.toro.template;

import com.apobates.forum.toro.BatchQueryFace;
import com.apobates.forum.toro.ResultMapperTransfer;
import com.apobates.forum.toro.template.strategy.TemplateBasisAffixStrategy;
import com.apobates.forum.toro.template.strategy.TemplateBatchAffixStrategy;
import com.apobates.forum.toro.template.strategy.TemplateSerialBasisAffixStrategy;
import com.apobates.forum.toro.template.strategy.TemplateSerialBatchAffixStrategy;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 属性前缀模板映射执行器
 * @param <E> 目标对象Class
 * @param <T> 初始对象类型
 * @author xiaofanku@live.cn
 * @since 2022-09-03
 */
public class TemplateAffixMapperExecutor<E,T> {
    private final Supplier<Collection<T>> selectObjSet;
    private final Class<E> className;
    private final boolean concurrent;

    public TemplateAffixMapperExecutor(Supplier<Collection<T>> selectObjSet, Class<E> className, boolean concurrent) {
        this.selectObjSet = selectObjSet;
        this.className = className;
        this.concurrent = concurrent;
    }

    public Supplier<Collection<T>> getSelectObjSet() {
        return selectObjSet;
    }

    public Class<E> getClassName() {
        return className;
    }

    public boolean isConcurrent() {
        return concurrent;
    }

    /**
     * [实例集合]设置最终结果的处理函数,包括: 消费函数 & 映射函数
     * @param transfer 最终结果处理函数
     * @return
     */
    public <F> BatchHandler<F> batch(ResultMapperTransfer<E,F> transfer) {
        return new BatchHandler<>(transfer);
    }

    /**
     * [实例集合]设置最终结果的消费函数
     * @param consumer 消费函数/前置处理
     * @return
     */
    public BatchHandler<E> batch(Consumer<E> consumer) {
        ResultMapperTransfer<E,E> transfer = new ResultMapperTransfer<>(){
            @Override
            public Consumer<E> getConsumer() {
                return consumer;
            }
            @Override
            public Function<E, E> getFormater() {
                return Function.identity();
            }
        };
        return new BatchHandler<>(transfer);
    }

    /**
     * [实例集合]设置最终结果的映射函数
     * @param formater 映射函数/后置转换
     * @return
     * @param <F>
     */
    public <F> BatchHandler<F> batch(Function<E,F> formater) {
        ResultMapperTransfer<E,F> transfer = new ResultMapperTransfer<>(){
            @Override
            public Consumer<E> getConsumer() {
                return (E ins)->logger.info("TemplateAffixMapperExecutor.BatchHandler Default Consumer");
            }
            @Override
            public Function<E, F> getFormater() {
                return formater;
            }
        };
        return new BatchHandler<>(transfer);
    }

    /**
     * [实例集合]绑定批量关系语句
     * @return
     */
    public <F> BatchHandler<F> batch(){
        return new BatchHandler<>(ResultMapperTransfer.empty());
    }

    /**
     * [单实例]设置最终结果的处理函数,包括: 消费函数 & 映射函数
     * @param transfer 最终结果处理函数
     * @return
     */
    public <F> BasisHandler<F> basis(ResultMapperTransfer<E,F> transfer) {
        return new BasisHandler<>(transfer);
    }

    /**
     * [单实例]设置最终结果的消费函数
     * @param consumer 消费函数/前置处理
     * @return
     */
    public BasisHandler<E> basis(Consumer<E> consumer) {
        ResultMapperTransfer<E,E> transfer = new ResultMapperTransfer<>(){
            @Override
            public Consumer<E> getConsumer() {
                return consumer;
            }
            @Override
            public Function<E, E> getFormater() {
                return Function.identity();
            }
        };
        return new BasisHandler<>(transfer);
    }

    /**
     * [单实例]设置最终结果的映射函数
     * @param formater 映射函数/后置转换
     * @return
     * @param <F>
     */
    public <F> BasisHandler<F> basis(Function<E,F> formater) {
        ResultMapperTransfer<E,F> transfer = new ResultMapperTransfer<>(){
            @Override
            public Consumer<E> getConsumer() {
                return (E ins)->logger.info("TemplateAffixMapperExecutor.BasisHandler Default Consumer");
            }
            @Override
            public Function<E, F> getFormater() {
                return formater;
            }
        };
        return new BasisHandler<>(transfer);
    }

    /**
     * [单实例]绑定基础关系语句
     * @return
     */
    public <F> BasisHandler<F> basis(){
        return new BasisHandler<>(ResultMapperTransfer.empty());
    }

    /**
     * 基础(单)执行句柄
     */
    public class BasisHandler<F>{
        private final ResultMapperTransfer<E,F> transfer;
        private Map<String, Function<String,?>> queries = new HashMap<>();

        public BasisHandler(ResultMapperTransfer<E, F> transfer) {
            this.transfer = transfer;
        }

        /**
         * 绑定标签和目标对象
         * @param tag 标签名，用于分组不同的聚合字段属于哪个类。例: Members
         * @param selectFunction 标签相关的对象映射函数
         * @return
         */
        public BasisHandler compose(String tag, Function<String,?> selectFunction) {
            this.queries.put(tag, selectFunction);
            return this;
        }

        /**
         * 使用内置的TemplateBasisAffixStrategy策略返回结果
         * @param statements
         * @return
         */
        public Optional<F> get(List<TemplateAffixStatements> statements) {
            return this.get(statements, new TemplateSerialBasisAffixStrategy<>());
        }

        /**
         * 使用指定的TemplateBasisAffixStrategy策略返回结果
         * @param statements
         * @param strategy
         * @return
         */
        public Optional<F> get(List<TemplateAffixStatements> statements, TemplateBasisAffixStrategy strategy) {
            T selectObj = new ArrayList<>(getSelectObjSet().get()).get(0);
            Optional<E> rs = strategy.apply(getClassName(), selectObj, statements, queries);
            return this.transfer.get(rs);
        }
    }

    /**
     * 批量执行句柄
     */
    public class BatchHandler<F>{
        private final ResultMapperTransfer<E,F> transfer;
        private Map<String, BatchQueryFace> queries = new HashMap<>();

        public BatchHandler(ResultMapperTransfer<E, F> transfer) {
            this.transfer = transfer;
        }

        /**
         * 绑定标签和目标对象
         * @param tag 标签名，用于分组不同的聚合字段属于哪个类。例: Members
         * @param selectFunction 标签相关的对象映射函数
         * @return
         */
        public BatchHandler compose(String tag, BatchQueryFace selectFunction) {
            this.queries.put(tag, selectFunction);
            return this;
        }

        /**
         * 使用内置的TemplateBatchAffixStrategy策略返回结果
         * @param statements
         * @return
         */
        public Collection<F> get(List<TemplateAffixStatements> statements) {
            return this.get(statements, new TemplateSerialBatchAffixStrategy<>());
        }

        /**
         * 使用指定的TemplateBatchAffixStrategy策略返回结果
         * @param statements
         * @param strategy
         * @return
         */
        public Collection<F> get(List<TemplateAffixStatements> statements, TemplateBatchAffixStrategy strategy) {
            Collection<E> rs = strategy.apply(getClassName(), getSelectObjSet().get(), statements, queries);
            return transfer.getAll(rs);
        }
    }
}
